/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.audit.controller;

import com.google.gson.Gson;
import com.koron.audit.domain.Audit;
import com.koron.audit.management.FlowManagement;
import com.koron.audit.service.api.AuditService;
import com.koron.audit.utils.BusinessCode;
import com.koron.common.StaffAttribute;
import com.koron.common.bean.StaffBean;
import com.koron.common.permission.SPIAccountAnno;
import com.koron.workflow.service.api.WorkflowService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.swan.bean.MessageBean;
import springfox.documentation.annotations.ApiIgnore;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Api(tags = "workflow", description = "工作流相关接口")
@RestController
@RequestMapping("/workflow")
public class WorkflowAction {
    private static Logger logger = Logger.getLogger(WorkflowAction.class);
    @Autowired
    private WorkflowService flowService;

    @Autowired
    private AuditService auditService;

    @Autowired
    private ApplicationContext ctx;

    @Autowired
    private FlowManagement flowManagement;

    private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();


    @ApiOperation(value = "流程处理")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "setCode", value = "流程模板组code", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "processCode", value = "流程模板code", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "billId", value = "业务单据编号(不能重复)", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "processinsId", value = "流程实例id", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "comment", value = "处理意见,只有取消沟通可以没有。", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "operation", value = "操作类型：1驳回、2转办、4添加沟通人、8催办、16废弃、32通过、64 添加沟通/评论信息、128取消沟通", required = true, paramType = "query", dataType = "Integer"),
            @ApiImplicitParam(name = "rejectNodeCode", value = "operation为1时  选择驳回到哪个节点的节点的名称", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "relatedUser", value = "操作对应的人员信息.operation为2和4 时该参数必须有，转办人和沟通人.", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "formVariables", value = "表单变量对象(JSON格式字符串)", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "otherNodeCandidates", value = "当配置有可修改必须修改节点时，指定节点处理人." +
                    "如流程设计时节点有设置权限属性“可修改节点或必须修改节点”，" +
                    "则：当operation为32时需指定对应节点的审批人" +
                    "多办理人以中划线隔开例子：\"kancha\":\"zhangsan-lisi-wanger\"}", paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "attachment", value = "附件标识", paramType = "query", dataType = "String")})
    @RequestMapping(value = "/submit.htm", method = {RequestMethod.POST})
    public MessageBean<?> submit(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, String setCode,
                                 String processCode, String processinsId, String billId, String taskId, Integer operation, String comment,
                                 String approverUserAccound, String rejectNodeCode, String relatedUser, String formVariables,
                                 String otherNodeCandidates, String attachment) {
        try {
            if (user == null) {
                MessageBean<?> msg = new MessageBean<>();
                msg.setCode(10000);
                msg.setDescription("审批人为空");
                return msg;
            }
            MessageBean<?> msg = flowService.submit(setCode, processCode, billId, user.getUserid(), taskId, approverUserAccound, comment, operation, rejectNodeCode, relatedUser, formVariables, otherNodeCandidates, attachment);
            //操作成功
            if (0 == msg.getCode()) {
                Gson gson = new Gson();
                Map map = gson.fromJson(gson.toJson(msg.getData()), Map.class);
                if (map.get("curNodes") != null && !StringUtils.isEmpty(map.get("curNodes").toString())) {
                    //提交后的当前节点编号（节点编号默认=id,可修改）（流程结束固定等于END,作废等于CANCEL,启动等于START）
                    List<Map<String, String>> curNodes = (List<Map<String, String>>) map.get("curNodes");
                    if (curNodes.size() > 0) {
                        for (Map<String, String> curNode : curNodes) {
                            if ("END".equals(curNode.get("code"))) {// 流程结束
                                singleThreadExecutor.submit(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            flowManagement.afterApprove(billId, ctx);
                                        } catch (Exception e) {
                                            logger.error(e.getMessage(),e);
                                        }
                                    }
                                });
                                break;
                            } else if ("CANCEL".equals(curNode.get("code"))) {// 废弃
                                singleThreadExecutor.submit(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            flowManagement.processDiscard(billId);
                                        } catch (Exception e) {
                                            logger.error(e.getMessage(),e);
                                        }
                                    }
                                });
                                break;
                            } else {
                                singleThreadExecutor.submit(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            flowManagement.approve(billId, operation, rejectNodeCode,relatedUser, map);
                                        } catch (Exception e) {
                                            logger.error(e.getMessage(),e);
                                        }
                                    }
                                });
                                break;
                            }
                        }
                    }
                }
            }
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            MessageBean<?> msg = new MessageBean<>();
            msg.setCode(20000);
            msg.setDescription("审批流程异常");
            return msg;
        }

    }

    @ApiOperation(value = "获取流程表单")
    @ApiImplicitParam(name = "auditId", value = "流程模板key", required = true, paramType = "query", dataType = "String")
    @RequestMapping(value = "/getView.htm", method = {RequestMethod.GET})
    public MessageBean<?> getView(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, @ApiIgnore String auditId) {
        MessageBean<String> msg = MessageBean.create(0, "success", String.class);
        if (null == user) {
            msg.setCode(BusinessCode.NOT_LOGIN.getCode());
            msg.setDescription(BusinessCode.NOT_LOGIN.getDescription());
            return msg;
        }
        try {
            Audit audit = auditService.queryOne(auditId);
            if (audit == null) {
                msg.setCode(BusinessCode.SUCCESS.getCode());
                msg.setDescription("获取流程表单失败");
                return msg;
            }
            String userid = user.getUserid();
            String taskId = null;
            String approverUserAccound = null;
            MessageBean<?> history = flowService.history(audit.getSetCode(), audit.getTemplateKey(), audit.getId());
            if (0 == history.getCode() && history.getData() != null) {
                List<Map> historys = (List<Map>) history.getData();
                if (historys != null && historys.size() > 0) {
                    List<Map> tasks = (List<Map>) historys.get(historys.size() - 1).get("tasks");
                    if (tasks != null && tasks.size() > 0 && tasks.get(0) != null) {
                        for (Map map : tasks) {
                            String userIds = map.get("user").toString();
                            if (userIds.contains(userid)) {
                                taskId = (String) map.get("taskId");
                                approverUserAccound = (String) map.get("user");
                            }
                        }
                    }
                }
            }
            String ret = flowService.view(audit.getSetCode(), audit.getTemplateKey(), user.getUserid(), taskId, approverUserAccound, audit.getFlowInstanceId());
            msg.setData(ret);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription("获取流程表单失败");
        }
        return msg;
    }

    @ApiOperation(value = "根据业务id获取流程表单")
    @ApiImplicitParam(name = "businessId", value = "业务id", required = true, paramType = "query", dataType = "String")
    @RequestMapping(value = "/getViewByBusinessId.htm", method = {RequestMethod.GET})
    public MessageBean<?> getViewByBusinessId(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, @ApiIgnore String businessId) {
        MessageBean<String> msg = MessageBean.create(0, "success", String.class);
        if (null == user) {
            msg.setCode(BusinessCode.NOT_LOGIN.getCode());
            msg.setDescription(BusinessCode.NOT_LOGIN.getDescription());
            return msg;
        }
        try {
            Audit audit = auditService.getAuditByBusinessId(businessId);
            if (audit == null) {
                msg.setCode(BusinessCode.SUCCESS.getCode());
                msg.setDescription("获取流程表单失败");
                return msg;
            }
            String userid = user.getUserid();
            String taskId = null;
            String approverUserAccound = null;
            MessageBean<?> history = flowService.history(audit.getSetCode(), audit.getTemplateKey(), audit.getId());
            if (0 == history.getCode() && history.getData() != null) {
                List<Map> historys = (List<Map>) history.getData();
                if (historys != null && historys.size() > 0) {
                    List<Map> tasks = (List<Map>) historys.get(historys.size() - 1).get("tasks");
                    if (tasks != null && tasks.size() > 0 && tasks.get(0) != null) {
                        for (Map map : tasks) {
                            String userIds = map.get("user").toString();
                            if (userIds.contains(userid)) {
                                taskId = (String) map.get("taskId");
                                approverUserAccound = (String) map.get("user");
                            }
                        }
                    }
                }
            }
            String ret = flowService.view(audit.getSetCode(), audit.getTemplateKey(), "", taskId, approverUserAccound, audit.getFlowInstanceId());
            msg.setData(ret);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription("获取流程表单失败");
        }
        return msg;
    }

    @ApiOperation(value = "移动端获取流程审批表单")
    @ApiImplicitParam(name = "auditId", value = "流程模板key", required = true, paramType = "query", dataType = "String")
    @RequestMapping(value = "/getAppView.htm", method = {RequestMethod.GET})
    public MessageBean<?> getAppView(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, @ApiIgnore String auditId) {
        MessageBean<String> msg = MessageBean.create(0, "success", String.class);
        if (null == user) {
            msg.setCode(BusinessCode.NOT_LOGIN.getCode());
            msg.setDescription(BusinessCode.NOT_LOGIN.getDescription());
            return msg;
        }
        try {
            Audit audit = auditService.queryOne(auditId);
            if (audit == null) {
                msg.setCode(BusinessCode.SUCCESS.getCode());
                msg.setDescription("获取流程审批表单失败");
                return msg;
            }
            String userid = user.getUserid();
            String taskId = null;
            String approverUserAccound = null;
            MessageBean<?> history = flowService.history(audit.getSetCode(), audit.getTemplateKey(), audit.getId());
            if (0 == history.getCode() && history.getData() != null) {
                List<Map> historys = (List<Map>) history.getData();
                if (historys != null && historys.size() > 0) {
                    List<Map> tasks = (List<Map>) historys.get(historys.size() - 1).get("tasks");
                    if (tasks != null && tasks.size() > 0 && tasks.get(0) != null) {
                        for (Map map : tasks) {
//                            if (userid.equals(map.get("user"))) {
//                                taskId = (String) map.get("taskId");
//                                approverUserAccound = (String) map.get("user");
//                            }
                            String userIds = map.get("user").toString();
                            if (userIds.contains(userid)) {
                                taskId = (String) map.get("taskId");
                                approverUserAccound = (String) map.get("user");
                            }
                        }
                    }
                }
            }
            String ret = flowService.appView(audit.getSetCode(), audit.getTemplateKey(), user.getUserid(), taskId, approverUserAccound, audit.getFlowInstanceId());
            msg.setData(ret);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription("获取流程审批表单失败");
        }
        return msg;
    }

    @ApiOperation(value = "移动端获取流程审批表单")
    @ApiImplicitParam(name = "auditId", value = "流程模板key", required = true, paramType = "query", dataType = "String")
    @RequestMapping(value = "/getAppHistoryView.htm", method = {RequestMethod.GET})
    public MessageBean<?> getAppHistoryView(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, @ApiIgnore String auditId) {
        MessageBean<String> msg = MessageBean.create(0, "success", String.class);
        if (null == user) {
            msg.setCode(BusinessCode.NOT_LOGIN.getCode());
            msg.setDescription(BusinessCode.NOT_LOGIN.getDescription());
            return msg;
        }
        try {
            Audit audit = auditService.queryOne(auditId);
            if (audit == null) {
                msg.setCode(BusinessCode.SUCCESS.getCode());
                msg.setDescription("获取流程审批表单失败");
                return msg;
            }
            if (StringUtils.isEmpty(audit.getFlowInstanceId())) {
                msg.setCode(BusinessCode.SUCCESS.getCode());
                msg.setDescription("获取流程审批表单失败");
                return msg;
            }
            String ret = flowService.appHistory(audit.getSetCode(), audit.getTemplateKey(), audit.getFlowInstanceId());
            msg.setData(ret);
            return msg;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription("获取流程审批表单失败");
            return msg;
        }
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @ApiOperation(value = "获取流程表单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "processinsId", value = "工作流实例Id", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "templateKey", value = "流程模板key", required = true, paramType = "query", dataType = "String")})
    @RequestMapping(value = "/getFormData.htm", method = {RequestMethod.GET})
    public String getFormData(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, @ApiIgnore String processinsId, @ApiIgnore String templateKey) {
        String ret = "";
        try {
            if (null == user) {
                return MessageBean.create(BusinessCode.NOT_LOGIN.getCode(), BusinessCode.NOT_LOGIN.getDescription(), Integer.class).toJson();
            }
            String userCode = user.getCode();
            String taskId = "";
            if (StringUtils.isEmpty(taskId)) {
                String grabHistory = flowService.grabHistory(processinsId);
                Map map = new Gson().fromJson(grabHistory, Map.class);
                if (map.get("data") != null) {
                    List<Map> list = (List<Map>) map.get("data");
                    if (!list.isEmpty()) {
                        map = list.get(0);
                        String nextcandidateUsers = (String) map.get("nextcandidateUsers");
                        if (StringUtils.isNotEmpty(nextcandidateUsers)) {
                            if (nextcandidateUsers.startsWith("1-")) {
                                userCode = "1-" + userCode;
                            }
                            String arry[] = nextcandidateUsers.split("[,，]");
                            List<String> arryList = new ArrayList<>(Arrays.asList(arry));
                            int i = -1;
                            if (arryList.size() > 1) {
                                i = arryList.indexOf(userCode);
                            }
                            taskId = (String) map.get("nexttaskId");
                            String[] taskIds = taskId.split("[,，]");
                            if (taskIds.length > 1) {
                                if (i == -1) {
                                    taskId = (String) map.get("nowtaskId");
//                            		taskId = taskIds[0];
                                } else {
                                    taskId = taskIds[i];
                                }
                            } else {
                                taskId = (String) map.get("nexttaskId");
                            }
                        } else {
                            taskId = (String) map.get("nexttaskId");
                            /*if(StringUtils.isBlank(taskId)){
                            	taskId = (String)map.get("nowtaskId");
                            }*/
                        }
                    }
                }
            }
            ret = flowService.workflowPresubmit(userCode, templateKey, taskId, processinsId);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(),e);
        }
        return ret;
    }


    @SuppressWarnings({"rawtypes", "unchecked"})
    @ApiOperation(value = "获取详情中的流程表单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "processinsId", value = "工作流实例Id", required = true, paramType = "query", dataType = "String")})
    @RequestMapping(value = "/getDetailFormData.htm", method = {RequestMethod.GET})
    public String getDetailFormData(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, @ApiIgnore String processinsId, @ApiIgnore String templateKey) {
        String ret = "";
        try {
            if (null == user) {
                return MessageBean.create(BusinessCode.NOT_LOGIN.getCode(), BusinessCode.NOT_LOGIN.getDescription(), Integer.class).toJson();
            }
            String userCode = "";
            String taskId = "";
            if (StringUtils.isEmpty(taskId)) {
                String grabHistory = flowService.grabHistory(processinsId);
                Map map = new Gson().fromJson(grabHistory, Map.class);
                if (map.get("data") != null) {
                    List<Map> list = (List<Map>) map.get("data");
                    if (!list.isEmpty()) {
                        map = list.get(0);
                        String nextcandidateUsers = (String) map.get("nextcandidateUsers");
                        if (StringUtils.isNotEmpty(nextcandidateUsers)) {
                            String arry[] = nextcandidateUsers.split("[,，]");
                            int i = 0;
                            if (arry.length > 1) {
                                for (String code : arry) {
                                    if (user.getCode().equals(code)) {
                                        break;
                                    } else {
                                        i++;
                                    }
                                }
                            }
                            taskId = (String) map.get("nexttaskId");
                            String[] taskIds = taskId.split("[,，]");
                            if (taskIds.length > 1) {
                                taskId = taskIds[i];
                            }
                        } else {
                            taskId = (String) ((String) map.get("nexttaskId"));
                        }
                    }
                }
            }
            ret = flowService.workflowPresubmit(userCode, templateKey, taskId, processinsId);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(),e);
        }
        return ret;
    }

    /*@ApiOperation(value = "获取流程列表")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "type", value = "type",  paramType = "query", dataType = "Integer")})
    @RequestMapping(value = "/getList.htm", method = {RequestMethod.GET})
    public MessageBean<?> getList(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, Integer type,Integer status) {
    	MessageBean<String> msg = MessageBean.create(0, "success", String.class);
    	if(null==user){
    		msg.setCode(BusinessCode.NOT_LOGIN.getCode());
            msg.setDescription(BusinessCode.NOT_LOGIN.getDescription());
            return msg;
        }
    	try {
    		flowService.list(null, null, null, null, null, null, type, 0, user.getUserid(), 0, 20000);
    	} catch (Exception e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription("获取数据失败");
        }
    	return msg;
    }*/
}
